/* Copyright 2001,2002,2003 NAH6
 * All Rights Reserved
 *
 * Parts Copyright DoD, Parts Copyright Starium
 *
 */
#include "celpfilt.h"


/**************************************************************************
*
* ROUTINE
*               do_pfilt
*               do_pfilt_dynamic
*
* FUNCTION
*               pole filter - given a filter structure
*               do_pfilt uses static coefficients
*               do_pfilt_dynamic uses changing coefficients
*
* SYNOPSIS
*               subroutine do_pfilt(flt, data)
*               subroutine do_pfilt_dynamic(flt, coef, data)
*
*   formal
*
*                       data    I/O
*       name            type    type    function
*       -------------------------------------------------------------------
*       flt             FILTER  i/o     FILTER structure
*       coef            fxpt_16  i      coefficients
*       data            fxpt_16 i/o     input/filtered output data
*
***************************************************************************
*
* DESCRIPTION
*
*       Recursive all-pole in-place time-domain filter.
*       The transfer function 1/A(z) is implemented
*       in a direct form realisation.
*
*                   N       -i
*       H(z) = 1 / SUM a(i)z         with a(0) = +1.0
*                  i=0
*
*       NOTE:  a(0) is not used for the actual computing,
*       as can easily be seen in the following flow graph.
*
*       x(t) ->---+------->--------(z0)-----> y(t)
*                 |                  |
*                 +-------< -a1 ----z1
*                 |                  |
*                 +-------< -a2 ----z2
*                 |                  |
*                 :                  :
*                 |                  |
*                 +-------< -aN ----zN
*
*
***************************************************************************
*
* CALLED BY
*
*       FindAdaptResidual FindLPCResidual UpdateEverything
*       HPF_InSpeech HPF_OutSpeech LPC_Synthesis PostFilter
*
***************************************************************************/

// we need to go 17.14 due to overflows!!!

#if 1
void do_pfilt(
  BIGFILTER *flt,
  fxpt_32 indata[],     /* 17.14 format */
  fxpt_16 outdata[])    /* 15.0  format */
{
  fxpt_32 m0, m1, m2;
  fxpt_32 c1, c2;
  fxpt_32 temp;

  fxpt_32 *in;
  fxpt_16 *out;

  ASSERT(flt->data_length == 240);
  ASSERT(flt->order == 2);

  m1 = flt->memory[1];
  m2 = flt->memory[2];
  c1 = flt->coef[1];
  c2 = flt->coef[2];

  in = indata;
  out = outdata;

  /*
   *  I tried reducing the number of shifts below, but I wasn't able to
   *  remove any of the remaining shifts without upsetting output binary
   *  backwards compatibility.  -DH  9/12/00
   */
  do {
#if 1
//    temp = fxpt_saturate32(((fxpt_64)m2*c2) >> 13);
    temp = fxpt_mult64_round_good(m2,c2,29);
    m0 = *in++ - temp;
//    temp = fxpt_saturate32(((fxpt_64)m1*c1) >> 13);
    temp = fxpt_mult64_round_good(m1,c1,29);
    m0 -= temp;
    m2 = m1;
    m1 = m0;

    //*out++ = (fxpt_16)(m0 >> 14);
    *out++ = fxpt_saturate16_round(m0,14);
#else
    temp = m2 >> 16;
    temp *= c2;
    temp <<= 3;
    m0 = *in++ - temp;
    m2 = m1;

    temp = m1 >> 16;
    temp *= c1;
    temp <<= 3;
    m0 -= temp;
    m1 = m0;

    *out++ = (m0 << 1) >> 15;
#endif

  } while (out != &outdata[240]);

  flt->memory[0] = m0;
  flt->memory[1] = m1;
  flt->memory[2] = m2;
}
#endif

